import { AxiosRequestConfig } from '../types'
import { isPlainObject, deepMerge } from '../helpers/util'

// 策略函数：优先取val2
function defaultStrat(val1: any, val2: any) {
  return typeof val2 === 'undefined'? val1: val2
}

// 策略函数：只取val2： url， params 、data
function fromVal2Strat(val1: any, val2: any) {
  if(typeof val2 !== 'undefined') {
    return val2
  }
}

// 深度拷贝策略
function deepMergeStrat(val1: any, val2: any) {
  if (isPlainObject(val2)) {
    return deepMerge(val1, val2)
  } else if (typeof val2 !== 'undefined') {
    return val2
  } else if (isPlainObject(val1)) {
    return deepMerge(val1)
  } else if (typeof val1 !== 'undefined') {
    return val1
  }
}

// 策略map
const strats = Object.create(null);

// 只取val2的几个属性
const staratkeysFromVal2 = ['url', 'params', 'data']
staratkeysFromVal2.forEach(key => {
  strats[key] = fromVal2Strat
})

// headers深度合并策略
const stratKeysDeepMerge = ['headers']

stratKeysDeepMerge.forEach(key => {
  strats[key] = deepMergeStrat
})


/**
 * @desctiption 合并请求参数，有一下3中情况
 * 1、优先取config2中字段： timeout、get
 * 2、只取config2中字段： url、params、data
 * 3、headers: config1和config2中字段深度合并
 * @params  config1, 默认配置
 * @params  config2, 用户传来配置配置
*/

function mergeConfig(config1: AxiosRequestConfig, config2?: AxiosRequestConfig): AxiosRequestConfig {
  if( !config2 ) {
    config2 = {}
  }
  
  // 保存合并后的结果
  const config = Object.create(null);
  
  for(let key in config2 ) {
    mergeField(key)
  }

  for(let key in config1 ) {
    if(!config2[key]) {
      mergeField(key)
    }
  }
  
  // 合并方法: 通过key来查找策略函数,并执行策略函数
  function mergeField(key: string) {
    // 策略函数
    const strat = strats[key] || defaultStrat;
    config[key] = strat(config1[key], config2![key])
  }

  return config;
}  



export default mergeConfig;